/***2025-01-21 迷途小羔羊
* 用于编写特效控制器
*/
namespace ghost{
    export class Effect{
        public static effectList:{[id:number]:Effect[]}={};
        /**添加特效
         * @param owner 此特效拥有者
         * @param ownerData 触发特效的技能数据
         * @param buffData 触发特效的buff
         * @param startTime 特效触发时间
         * @param type 特效类型
         * @param effectArr 特效参数 默认null
         * @param targetX 目标x 默认NaN
         * @param targetY 目标y 默认NaN
         * @param direction 方向 默认0
         * @param floatH 高度 默认NaN
         * @param creator 特效的创造者(例如由角色攻击动作产生的，则是角色，如受击特效由攻击特效产生的，则是攻击特效) 默认null
         * @param target 特效的攻击目标 默认null
        */
        public static addEffect(owner:GameRole, ownerData:OwnerData, startTime:number, type:EffectType, effectArr:EffectArray=null, targetX:number=NaN, targetY:number=NaN, direction:number=0, floatH:number=NaN, creator:GameRole=null, target:GameRole=null):void
        {
            if(effectArr && effectArr.length > 0)
            {
                let effect:Effect = new Effect();                
                effect.setOwnerData(SceneManager.instance, owner, ownerData, creator, target);
                effect.effectSet(startTime, type, effectArr, targetX, targetY, direction, ownerData._skillData, floatH);
                if(Effect.effectList[owner._id] == null)
                    Effect.effectList[owner._id] = [];
                Effect.effectList[owner._id].push(effect);
            }            
        }
        /**移除buff特效
         * @param owner buff拥有者
         * @param id buff唯一id
        */
        // public static removeBuffEffect(owner:GameRole, id:number):void
        // {
        //     let arr:Effect[];
        //     let len:number;
        //     let effect:Effect;
        //     arr = Effect.effectList[owner._id];
        //     if(arr)
        //     {
        //         len = arr.length;
        //         while(--len > -1)
        //         {
        //             effect = arr[len];
        //             if(effect._buffData && effect._buffData.id == id)
        //                 effect.dispose();
        //         }   
        //     } 
        // }
        /**销毁特效
         * @param id 角色id，默认-1，表示清理全部
        */
        public static dispose(id:number=-1):void
        {
            let arr:Effect[];
			let len:number;
            if(id == -1)
            {
                arr = Effect.effectList[id];
                if(arr)
                {
                    len = arr.length;
                    while(--len > -1)
                        arr[len].dispose();
                }                
            }
            else
            {
                for(var key in Effect.effectList)
                {				
                    arr = Effect.effectList[key];
                    if(arr)
                    {
                        len = arr.length;
                        while(--len > -1)
                            arr[len].dispose();
                    }                    
                }
            }
        }
        public static pauseAll():void
        {
            let s = this;
            for(var key in Effect.effectList)            
                Effect.pause(Number(key));
        }
        public static resumeAll():void
        {
            let s = this;
            for(var key in Effect.effectList)            
                Effect.resume(Number(key));
        }
        public static pause(poolId:number):void
        {
            let arr:Effect[];
            let len:number;
            arr = Effect.effectList[poolId];
            if(arr && arr.length > 0)
            {
                len = arr.length;
                while(--len > -1)
                    arr[len].resume();
            }            
        }
        public static resume(poolId:number):void
        {
            let arr:Effect[];
            let len:number;
            arr = Effect.effectList[poolId];
            if(arr && arr.length > 0)
            {
                len = arr.length;
                while(--len > -1)
                    arr[len].resume();
            }            
        }
        /**特效类型*/      
        protected _type:EffectType;
        /**当前进行等待播放的特效配置*/
        protected _effectArray:EffectArray;
        protected _targetX:number;
        protected _targetY:number;
        protected _targetH:number;
        protected _targetDir:number;
        protected _direction:number;
        /**特效的拥有者*/
        private _owner:GameRole;
        public _ownerId:number;
        /**特效的创建者(如果是攻击特效此对象会跟ownerData.owner的一样，如果是受击特效则可能是攻击特效)*/
        private _creator:GameRole;
        private _creatorId:number;
        private _target:GameRole;
        private _targetId:number;
        private _scene:SceneManager;
        private _skill:ISkillData;
        // private _buff:Object_buff;
        // public _buffData:IBuffData;        
        private _ownerData:OwnerData;
        // private _alreadyCD:boolean;
        // public hurtAdd:GYLite.ExpTree[];
        protected _paused:boolean;
		protected _pauseTime:number;
		protected _pauseStartTime:number;
        /**是否可以暂停*/public canPause:boolean;
        constructor()
        {
            let s= this;
            s._pauseTime = 0;
        }
        /**设置对象参数
         * @param scene 所属场景
         * @param owner 此特效拥有者
         * @param ownerData 触发特效的技能数据
         * @param creator 特效的创造者
         * @param target 特效的攻击目标
         * 
        */
        public setOwnerData(scene:SceneManager, owner:GameRole, ownerData:OwnerData, creator:GameRole=null, target:GameRole=null):void
        {
            let s= this;
            s._ownerData = ownerData;            
            s._owner = owner;
            s._scene = scene;
            s._ownerId = s._owner._id;
            s._creator = creator?creator:ownerData._owner;
            s._creatorId = creator?creator._id:ownerData._owner._id;
            s._target = target;
            s._targetId = target?target._id:NaN;
        }
        
        /**添加特效
		 * @param startTime 特效起始时间
         * @param type 特效类型
         * @param effectArr 特效配置数组
         * @param targetX 施法目标坐标x
         * @param targetY 施法目标坐标y
         * @param direction 施法朝向
         * @param skill 特效所属的技能
         * @param hurtAdd 特效造成的伤害加成(技能或者buff)
         * @param targetH 施法目标高度
		*/
        public effectSet(startTime:number, type:EffectType, effectArr:EffectArray=null, targetX:number=NaN, targetY:number=NaN, direction:number=0, skill:ISkillData=null, targetH:number=NaN):void
        {
            let s= this;
            let arr:EffectArray;                                     
            if(effectArr && effectArr.length > 0)
            {
                s._skill = skill;
                // s._buffData = buffData;
                // s._buff = buffData?buffData.buffCfg:null;
                // s.hurtAdd = (s._buff && BuffCfg.buffNumFormula[s._buff.id])?[BuffCfg.buffNumFormula[s._buff.id]]:null;                
                s._targetX = targetX;
                s._targetY = targetY;
                s._targetH = targetH;                
                s._direction = direction;
                s._type = type;
                arr = effectArr.concat();
                arr = arr.reverse();                
                if(startTime == startTime)
                    arr.timeTicker = (new map2D.TimeTicker(s._scene)).init(startTime,NaN);
                s._effectArray = arr;
            }            
        }
        public excLoop(t:number):void
        {
            let s= this;
			let len:number;
            let effect:EffectParamsCfg;    
            let deg:number;
            let objBase:ObjBase;
            let absX:number,absY:number;
            let isAttack:boolean,isAOE:boolean;
            if(!s.ownerIsValid())
            {
                s.dispose();
                return;
            }
            if(s._paused)
				return;				
			t = t - s._pauseTime;	
            isAttack = s._type == EffectType.ATTACK;            
            let floatH:number;
            let gap:number;
            let offsetX: number,offsetY:number,dir:number,dis:number;
            let buffEffect:EffectObj;
            
            len = s._effectArray.length;
            while (--len > -1)
            {
                effect = s._effectArray[len];
                isAOE = effect.flyUseTime == 0;
                effect.timeTicker && effect.timeTicker.playRateUpdate();
                if (effect.time >= 0) {					
                    if (s._effectArray.timeTicker == null || t - s._effectArray.timeTicker.startTime >= effect.time) {
                        // if(s._type == EffectType.BUFF)//由于buff特效不重复叠加，检测已经存在则直接把buffData加入到对应特效中
                        // {
                        //     buffEffect = s._owner.findBuffEffect(String(effect.id));
                        //     if(buffEffect)
                        //     {
                        //         if(buffEffect._isBuffDataBind && s._buffData.effect == null)//只加一次
                        //             buffEffect.addBuffData(s._buffData);
                        //         s._effectArray.splice(len, 1);
                        //         continue;
                        //     }                            
                        // }
                        if(!RoleConfig.getEffectObj(s._type, String(effect.id), effect.layer))
                        {
                            s._effectArray.splice(len, 1);
                            return;
                        }                            
                        if(isAttack || s._type == EffectType.SINGLE)
                        {
                            let per:number;
                            gap = 1;
                            //大于0相当于直接设置高度，否则当作相对身高的百分比，默认0.5，但如果是aoe特效则默认是0
                            if(effect.offsetH > 0)
                            {
                                if(effect.offsetH < 1) //小数                                
                                    floatH = s._owner.altitude + s._owner.headH * effect.offsetH;                                
                                else
                                    floatH = effect.offsetH;
                            }
                            else
                            {
                                per = (effect.flyUseTime > 0 || s._type == EffectType.SINGLE)?0.5:0;
                                floatH = s._owner.altitude + s._owner.headH * per;
                            }
                        }
                        else
                        {
                            floatH = gap = 0;
                        }                                                 
                        if(effect.layer == map2D.LayerType.ROLE_BACK || effect.layer == map2D.LayerType.ROLE_FRONT)
                        {
                            absX = effect.offsetX;
                            absY = effect.offsetY;
                        }
                        else
                        {
                            if(isAttack && isAOE)
                            {//aoe攻击相对目标作偏移
                                absX = s._targetX + effect.offsetX;
                                absY = s._targetY + effect.offsetY;
                            }
                            else
                            {//弹道攻击相对目标作偏移
                                if(effect.offsetX != 0 || effect.offsetY != 0)
                                {
                                    deg = map2D.DirectionType.getDirectorDeg(s._owner.direction);
                                    // dis = Math.pow(effect.offsetX*effect.offsetX+effect.offsetY*effect.offsetY,0.5);
                                    offsetX = effect.offsetX * MathUtil.cos(deg) - effect.offsetY * MathUtil.sin(deg);
                                    offsetY = effect.offsetX * MathUtil.sin(deg) + effect.offsetY * MathUtil.cos(deg);
                                }
                                else
                                {
                                    offsetX = 0;
                                    offsetY = 0;
                                }
                                absX = s._owner.absX + offsetX;
                                absY = s._owner.absY + offsetY;
                            }
                        }                         
                        if(s._targetX == s._targetX && s._targetY == s._targetY)
                            s._targetDir = map2D.DirectionType.getDirectorSts(PositionUtil.calculateAngle(s._targetX, s._targetY, s._owner.absX,s._owner.absY));
                        else if(effect.notDir > 2)//大于2类型的属于根据特效产生对象的方向，否则则是拥有此特效的对象
                            s._targetDir = s._creator.absX < s._owner.absX?map2D.DirectionType.RIGHT:map2D.DirectionType.LEFT;
                        else
                            s._targetDir = s._owner._scaleDir;
                        
                        dir = (effect.notDir == 0 || effect.notDir == 3)?s._targetDir:(effect.notDir == 1?map2D.DirectionType.RIGHT:(s._targetDir + 4) % 8);
                        objBase = s._scene.createEffectToScene(s._owner, String(effect.id), absX, absY + gap, s._type, s._targetDir, floatH, effect.layer);
                        // objBase.hurtAdd = s.hurtAdd;
                        objBase.setOwnerData(s._ownerData);
                        if(s._type == EffectType.ATTACK)
                        {
                            let driftObj:DriftObj = <DriftObj>objBase;                            
                            driftObj.penatrateNum = effect.penatrateNum>0?effect.penatrateNum:999999;
                            driftObj.setBalistic(effect.ballisticParams);                            
                            driftObj.setHitLitmit(effect.hitLimit);
                            driftObj.setFlyUserTime(effect.flyUseTime|0, effect.notRotate);//获得飞行速度后才能确定目标方向是否随角度旋转
                            driftObj.setAttackTarPos(s._targetX, s._targetY + gap, effect.reachDisappear==1, s._targetH, s._target);
                        }
                        // else if(s._type == EffectType.BUFF)
                        // {                            
                        //     let driftObj:EffectObj = <EffectObj>objBase;   
                        //     if(s._buffData.effect == null)
                        //         driftObj.addBuffData(s._buffData);
                        // }
                        s._effectArray.splice(len, 1);
                    }                                        
                }
            }
            if(s._effectArray.length == 0)
                s.dispose();
        }
        public dispose():void
        {
            let s= this;
            let ind:number;
            let arr:Effect[];
            arr = Effect.effectList[s._ownerId];
            if(arr)
            {
                ind = arr.indexOf(s);
                if(ind > -1)
                    arr.splice(ind, 1);
                if(arr.length == 0)
                    delete Effect.effectList[s._ownerId];
            }            
            s._effectArray.length = 0;
            // if(s._buff)
            // {
            //     s._buff = null;
            // }
        }
        /**拥有者是否失效*/
        public ownerIsValid():boolean
        {
            let s = this;
            return s._owner._id == s._ownerId;
        }
        /**创建者是否失效*/
        public creatorIsValid():boolean
        {
            let s = this;
            return s._creator._id == s._creatorId;
        }
        /**目标是否失效*/
        public targetIsValid():boolean
        {
            let s = this;
            return s._target._id == s._targetId;
        }
        public pause():void
		{
			let s =this;
			if(s._paused)return;
			s._paused = true;
			s._pauseStartTime = s._scene.timeTick;
			s.pause();
		}
		public resume():void
		{
			let s = this;
			if(!s._paused)return;
			s._paused = false;
			s._pauseTime += s._scene.timeTick - s._pauseStartTime;
		}
    }
}